<template>
  <div ref="select" class="select "  :class="{'is-open': isOpen, 'plain': props.plain}">
    <span class="placeholder"
          :class="{empty: currentValue == null || currentValue === ''}"
          @click.stop="isOpen = !isOpen">{{ currentItem ? getName(currentItem) : currentValue?getName(currentValue):placeholder }}</span>
    <ul>
      <li v-for="item in config"
          :class="{on: showOn(item)}"
          :key="typeof item==='string'?item:item.name"
          @click.stop="handleChange(item)"
      >{{ getName(item) }}
      </li>
    </ul>
  </div>
</template>

<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'

interface OptionItem {
  name: string
  value: string | number,

  [propName: string]: any
}

interface Props {
  placeholder?: string
  modelValue: string
  data?: Array<OptionItem | string>
  plain?: boolean
  options?: {
    propValue: string
    propName: string
  }
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  placeholder: '请选择',
  plain: false,
  data: () => []
})
const emit = defineEmits(['update:modelValue', 'change'])

const select = ref<HTMLDivElement | null>(null)
const currentValue = ref<string | null>()
const currentItem = ref<OptionItem | string>()
const isOpen = ref(false)


const config = ref<Props['data']>([])
const nameKey = computed(() => {
  return props.options?.propName ? props.options?.propName : 'name'
})
const valueKey = computed(() => {
  return props.options?.propValue ? props.options?.propValue : 'value'
})
const isArrayStr = computed(() => {
  return typeof props.data[0] === 'string'
})

const getName = (item: OptionItem | string) => {
  if (!item){
    return  ''
  }
  if (typeof item === 'string'){
    return  item
  }
  return  item[nameKey.value]
}
const showOn = (item: OptionItem | string) => {
  if (typeof item === 'string'){
    return currentValue.value === item
  }
  return currentValue.value === item[valueKey.value]
}
watch(() => props.data, (val) => {
  config.value = val
}, {
  deep: true,
  immediate: true
})
watch(() => props.modelValue, (val) => {
  const item:any = config.value?.find((option: any)=>{
    if (typeof option === 'string'){
      return  option === val
    }
    return option[valueKey.value] === val
  })
  if (item){
    currentItem.value = item
    currentValue.value = typeof item === 'string' ? item : item[valueKey.value]
  }
}, {
  immediate: true
})
const handleChange = (item: OptionItem | string) => {
  currentItem.value = item
  currentValue.value = typeof item === 'string' ? item : item[valueKey.value]
  emit('update:modelValue', currentValue.value)
  emit('change', currentItem.value)
  hidden()
}

const hidden = () => {
  isOpen.value = false
}

const closeSelect = () => {
  hidden()
}
onMounted(() => {
  document.body.addEventListener('click', closeSelect)
})

onUnmounted(() => {
  document.body.removeEventListener('click', closeSelect)
})
</script>
<style scoped lang="scss">
@import "./index";
</style>
